import jsYaml from 'js-yaml';
// xml-js 使用 CommonJS 导出，为保证兼容性使用命名空间导入
import * as xmljs from 'xml-js';
import type { Template, TemplateField } from './storage';

// 处理后的字段类型（用于YAML/XML输出）
interface ProcessedField {
  name: string;
  type: string;
  required: boolean;
  constraint: string;
  format: string;
  nestedTemplate?: {
    name: string;
    id: string;
    fields: ProcessedField[];
  };
}

/**
 * 转换数据为YAML格式
 * @param {Template | null} data 要转换的数据
 * @param {Template[]} allTemplates 所有模板列表，用于处理嵌套
 * @returns {string} YAML字符串
 */
export const toYaml = (data: Template | null, allTemplates: Template[]): string => {
  try {
    if (!data || !data.name) return '# 请输入模板名称并添加字段';

    // 递归处理嵌套字段
    const processFields = (fields: TemplateField[]): ProcessedField[] => {
      return (fields || []).map(field => {
        if (!field || !field.name) return null;

        const processed: ProcessedField = {
          name: field.name,
          type: field.type,
          required: field.required,
          constraint: field.constraint || '',
          format: field.format || ''
        };

        // 如果是模板嵌套类型，添加嵌套信息
        if (field.type === 'template' && field.templateId && field.templateId.trim() !== '') {
          const nestedTpl = allTemplates.find(t => t.id === field.templateId);
          if (nestedTpl) {
            processed.nestedTemplate = {
              name: nestedTpl.name,
              id: nestedTpl.id,
              fields: processFields(nestedTpl.fields)
            };
          }
        }

        return processed;
      }).filter((f): f is ProcessedField => f !== null);
    };

    // 准备要转换的数据结构
    const yamlData = {
      name: data.name,
      description: data.description || '',
      fields: processFields(data.fields)
    };

    return jsYaml.dump(yamlData, { indent: 2 });
  } catch (error) {
    const err = error as Error;
    return `# YAML格式错误: ${err.message}`;
  }
};

// XML字段类型
interface XmlField {
  _attributes: {
    name: string;
    type: string;
    required: boolean;
    constraint: string;
    format: string;
  };
  nestedTemplate?: {
    _attributes: {
      name: string;
      id: string;
    };
    fields: {
      field: XmlField[];
    };
  };
}

/**
 * 转换数据为XML格式
 * @param {Template | null} data 要转换的数据
 * @param {Template[]} allTemplates 所有模板列表，用于处理嵌套
 * @returns {string} XML字符串
 */
export const toXml = (data: Template | null, allTemplates: Template[]): string => {
  try {
    if (!data || !data.name) return '<!-- 请输入模板名称并添加字段 -->';

    const processFields = (fields: TemplateField[]): XmlField[] => {
      const arr = (fields || []).map(field => {
        if (!field || !field.name) return null;
        const f: XmlField = {
          _attributes: {
            name: field.name,
            type: field.type,
            required: field.required,
            constraint: field.constraint || '',
            format: field.format || ''
          }
        };

        if (field.type === 'template' && field.templateId && field.templateId.trim() !== '') {
          const nestedTpl = allTemplates.find(t => t.id === field.templateId);
          if (nestedTpl) {
            f.nestedTemplate = {
              _attributes: {
                name: nestedTpl.name,
                id: nestedTpl.id
              },
              fields: {
                field: processFields(nestedTpl.fields).filter((f): f is XmlField => f !== null)
              }
            };
          }
        }

        return f;
      }).filter((f): f is XmlField => f !== null);
      return arr;
    };

    // 准备要转换的数据结构
    const xmlData = {
      _declaration: { _attributes: { version: '1.0', encoding: 'UTF-8' } },
      template: {
        _attributes: {
          name: data.name,
          description: data.description || ''
        },
        fields: {
          field: processFields(data.fields)
        }
      }
    };

    // 使用 xml-js 的 js2xml 方法将 JS 对象转换为 XML 字符串
    return xmljs.js2xml(xmlData, { compact: true, spaces: 2 });
  } catch (error) {
    const err = error as Error;
    return `<!-- XML格式错误: ${err.message} -->`;
  }
};

